import type { Node, Edge } from "reactflow"
import type { NodeConfig } from "./node-configs"

// 文件定义
export interface FileNode {
  name: string
  path: string
  content: string
  language: "python" | "typescript" | "json" | "yaml"
}

// 目录定义
export interface DirectoryNode {
  name: string
  path: string
  files: FileNode[]
  subdirectories: DirectoryNode[]
}

// 分层代码（重新设计）
export interface LayeredCodeV2 {
  layer: string
  title: string
  description: string
  color: string
  directory: DirectoryNode
}

// 生成的代码结构
export interface GeneratedLangGraphCodeV2 {
  fullCode: string
  layers: LayeredCodeV2[]
  summary: {
    nodeCount: number
    edgeCount: number
    fileCount: number
    layers: string[]
  }
}

/**
 * LangGraph 分层代码生成器 V2
 * 支持目录结构和文件展示
 */
export class LangGraphCodeGeneratorV2 {
  private nodes: Node[]
  private edges: Edge[]
  private nodeConfigs: Map<string, NodeConfig>
  private workflowId: string

  constructor(nodes: Node[], edges: Edge[], nodeConfigs: NodeConfig[]) {
    this.nodes = nodes
    this.edges = edges
    this.nodeConfigs = new Map(nodeConfigs.map((c) => [c.type, c]))
    this.workflowId = `workflow_${Date.now()}`
  }

  /**
   * 生成完整的分层代码
   */
  generate(): GeneratedLangGraphCodeV2 {
    const layers: LayeredCodeV2[] = []

    // Layer 1: FastAPI 服务层
    layers.push(this.generateLayer2())

    // Layer 2: Agent 管理层
    layers.push(this.generateLayer3())

    // Layer 3: Agent 执行层（核心工作流代码）
    layers.push(this.generateLayer4())

    // Layer 4: 工具与集成层
    layers.push(this.generateLayer5())

    // Layer 5: 基础设施层
    layers.push(this.generateLayer6())

    // 计算文件总数
    const fileCount = layers.reduce((total, layer) => {
      return total + this.countFiles(layer.directory)
    }, 0)

    return {
      fullCode: this.generateFullCode(layers),
      layers,
      summary: {
        nodeCount: this.nodes.length,
        edgeCount: this.edges.length,
        fileCount,
        layers: layers.map((l) => l.layer),
      },
    }
  }

  private countFiles(dir: DirectoryNode): number {
    let count = dir.files.length
    dir.subdirectories.forEach((subdir) => {
      count += this.countFiles(subdir)
    })
    return count
  }

  private generateLayer1(): LayeredCodeV2 {
    return {
      layer: "Layer 1",
      title: "用户接入层 (User Interface Layer)",
      description: "Web界面、REST API、命令行工具",
      color: "#e3f2fd",
      directory: {
        name: "frontend",
        path: "/frontend",
        files: [
          {
            name: "workflow-builder.tsx",
            path: "/frontend/components/workflow-builder.tsx",
            language: "typescript",
            content: `"use client"

import { WorkflowCanvas } from "./workflow-canvas"
import { NodeLibrary } from "./node-library"
import { PropertyPanel } from "./property-panel"

export function WorkflowBuilder() {
  // 工作流构建器主组件
  // 提供可视化拖拽界面
  // 节点数量: ${this.nodes.length}
  // 连接数量: ${this.edges.length}

  return (
    <div className="flex h-screen">
      <NodeLibrary />
      <WorkflowCanvas />
      <PropertyPanel />
    </div>
  )
}`,
          },
          {
            name: "api-client.ts",
            path: "/frontend/lib/api-client.ts",
            language: "typescript",
            content: `export class WorkflowAPIClient {
  private baseUrl = "http://localhost:8000"

  async executeWorkflow(workflowId: string, input: any) {
    const response = await fetch(\`\${this.baseUrl}/api/workflows/execute\`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ workflow_id: workflowId, input })
    })
    return response.json()
  }

  async saveWorkflow(workflowData: any) {
    const response = await fetch(\`\${this.baseUrl}/api/workflows\`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(workflowData)
    })
    return response.json()
  }
}`,
          },
        ],
        subdirectories: [],
      },
    }
  }

  private generateLayer2(): LayeredCodeV2 {
    return {
      layer: "Layer 1",
      title: "FastAPI 服务层 (API Service Layer)",
      description: "路由层、中间件、服务层",
      color: "#f3e5f5",
      directory: {
        name: "api",
        path: "/api",
        files: [
          {
            name: "main.py",
            path: "/api/main.py",
            language: "python",
            content: `from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from .routes import workflow_router, agent_router

app = FastAPI(title="${this.workflowId} API", version="1.0.0")

# CORS 配置
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 注册路由
app.include_router(workflow_router, prefix="/api/workflows", tags=["workflows"])
app.include_router(agent_router, prefix="/api/agents", tags=["agents"])

@app.get("/")
async def root():
    return {"message": "LangGraph Workflow API", "version": "1.0.0"}`,
          },
          {
            name: "routes.py",
            path: "/api/routes.py",
            language: "python",
            content: `from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from typing import Dict, Any, Optional
from .services import WorkflowService

workflow_router = APIRouter()
agent_router = APIRouter()

# 请求模型
class WorkflowExecuteRequest(BaseModel):
    workflow_id: str
    input: Dict[str, Any]
    config: Optional[Dict[str, Any]] = None

class WorkflowExecuteResponse(BaseModel):
    success: bool
    result: Any
    metadata: Dict[str, Any]

# 工作流路由
@workflow_router.post("/execute", response_model=WorkflowExecuteResponse)
async def execute_workflow(request: WorkflowExecuteRequest):
    """执行工作流"""
    try:
        service = WorkflowService()
        result = await service.execute(
            workflow_id=request.workflow_id,
            input_data=request.input,
            config=request.config
        )
        return WorkflowExecuteResponse(
            success=True,
            result=result,
            metadata={"workflow_id": request.workflow_id}
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@workflow_router.get("/{workflow_id}")
async def get_workflow(workflow_id: str):
    """获取工作流配置"""
    service = WorkflowService()
    return await service.get_workflow(workflow_id)`,
          },
          {
            name: "services.py",
            path: "/api/services.py",
            language: "python",
            content: `from typing import Dict, Any, Optional
from ..agent_manager import agent_manager

class WorkflowService:
    """工作流服务"""

    async def execute(
        self,
        workflow_id: str,
        input_data: Dict[str, Any],
        config: Optional[Dict[str, Any]] = None
    ) -> Any:
        """执行工作流"""
        return await agent_manager.execute(
            workflow_id=workflow_id,
            input_data=input_data,
            config=config
        )

    async def get_workflow(self, workflow_id: str) -> Dict[str, Any]:
        """获取工作流配置"""
        return {
            "workflow_id": workflow_id,
            "nodes": ${this.nodes.length},
            "edges": ${this.edges.length}
        }`,
          },
        ],
        subdirectories: [],
      },
    }
  }

  private generateLayer3(): LayeredCodeV2 {
    return {
      layer: "Layer 2",
      title: "Agent 管理层 (Agent Management Layer)",
      description: "Agent管理器、通信管理器、并发管理器",
      color: "#e8f5e8",
      directory: {
        name: "agent_manager",
        path: "/agent_manager",
        files: [
          {
            name: "__init__.py",
            path: "/agent_manager/__init__.py",
            language: "python",
            content: `from .manager import AgentManager, agent_manager
from .context import ExecutionContext

__all__ = ["AgentManager", "agent_manager", "ExecutionContext"]`,
          },
          {
            name: "manager.py",
            path: "/agent_manager/manager.py",
            language: "python",
            content: `from typing import Dict, Any, List, Optional
from datetime import datetime
from .context import ExecutionContext
import logging

logger = logging.getLogger(__name__)

class AgentManager:
    """Agent 生命周期管理器"""

    def __init__(self):
        self.agents: Dict[str, Any] = {}
        self.execution_history: List[Dict] = []

    async def execute(
        self,
        workflow_id: str,
        input_data: Dict[str, Any],
        config: Optional[Dict[str, Any]] = None
    ) -> Any:
        """执行 Agent 工作流"""

        # 1. 验证工作流配置
        workflow_config = self.validate_workflow(workflow_id)

        # 2. 初始化执行上下文
        context = ExecutionContext(
            workflow_id=workflow_id,
            input_data=input_data,
            config=config or {},
            timestamp=datetime.now()
        )

        # 3. 创建或获取 Agent 实例
        agent = await self.get_or_create_agent(workflow_id, workflow_config)

        # 4. 执行工作流
        result = await agent.run(context)

        # 5. 记录执行历史
        self.execution_history.append({
            "workflow_id": workflow_id,
            "timestamp": context.timestamp,
            "result": result
        })

        return result

    def validate_workflow(self, workflow_id: str) -> Dict:
        """验证工作流配置"""
        return {
            "nodes": ${this.nodes.length},
            "edges": ${this.edges.length},
            "valid": True
        }

    async def get_or_create_agent(
        self,
        workflow_id: str,
        config: Dict
    ):
        """获取或创建 Agent 实例"""
        if workflow_id not in self.agents:
            from ..agents import WorkflowAgent
            self.agents[workflow_id] = WorkflowAgent(config)
        return self.agents[workflow_id]

# 全局 Agent 管理器实例
agent_manager = AgentManager()`,
          },
          {
            name: "context.py",
            path: "/agent_manager/context.py",
            language: "python",
            content: `from typing import Dict, Any
from datetime import datetime
from dataclasses import dataclass

@dataclass
class ExecutionContext:
    """执行上下文"""
    workflow_id: str
    input_data: Dict[str, Any]
    config: Dict[str, Any]
    timestamp: datetime`,
          },
        ],
        subdirectories: [],
      },
    }
  }

  private generateLayer4(): LayeredCodeV2 {
    const nodeFunctions = this.generateNodeFunctions()

    return {
      layer: "Layer 3",
      title: "Agent 执行层 (Agent Execution Layer)",
      description: "预构建Agent、自定义Agent、混合Agent - 基于拖拽节点动态生成",
      color: "#fff3e0",
      directory: {
        name: "agents",
        path: "/agents",
        files: [
          {
            name: "__init__.py",
            path: "/agents/__init__.py",
            language: "python",
            content: `from .workflow_agent import WorkflowAgent
from .state import WorkflowState

__all__ = ["WorkflowAgent", "WorkflowState"]`,
          },
          {
            name: "state.py",
            path: "/agents/state.py",
            language: "python",
            content: `from typing import TypedDict, Annotated, List, Dict, Any
from operator import add

class WorkflowState(TypedDict):
    """工作流状态定义"""
    messages: Annotated[List[str], add]  # 消息历史
    current_step: str  # 当前步骤
    input_data: Dict[str, Any]  # 输入数据
    output_data: Dict[str, Any]  # 输出数据
    metadata: Dict[str, Any]  # 元数据

    # 基于拖拽节点的自定义字段
${this.nodes.map(node => `    ${this.sanitizeName(node.id)}_result: Any  # ${node.data.label} 节点结果`).join('\n')}`,
          },
          {
            name: "nodes.py",
            path: "/agents/nodes.py",
            language: "python",
            content: `from .state import WorkflowState
from typing import Dict, Any
import logging

logger = logging.getLogger(__name__)

# ========================================
# 节点实现 (基于拖拽的 ${this.nodes.length} 个节点)
# ========================================

${nodeFunctions}`,
          },
          {
            name: "workflow_agent.py",
            path: "/agents/workflow_agent.py",
            language: "python",
            content: `from langgraph.graph import StateGraph, END
from .state import WorkflowState
from .nodes import *
from typing import Dict, Any
import logging

logger = logging.getLogger(__name__)

class WorkflowAgent:
    """工作流 Agent 主类"""

    def __init__(self, config: Dict):
        self.config = config
        self.graph = self.build_graph()

    def build_graph(self) -> StateGraph:
        """构建工作流图"""
        # 创建状态图
        workflow = StateGraph(WorkflowState)

        # 添加节点 (${this.nodes.length} 个)
${this.nodes.map(node => `        workflow.add_node("${node.id}", ${this.sanitizeName(node.id)})`).join('\n')}

        # 设置入口点
${this.nodes.length > 0 ? `        workflow.set_entry_point("${this.nodes[0].id}")` : '        # 无节点'}

        # 添加边 (${this.edges.length} 条连接)
${this.edges.map(edge => `        workflow.add_edge("${edge.source}", "${edge.target}")`).join('\n')}

        # 连接到结束
${this.nodes.length > 0 ? `        workflow.add_edge("${this.nodes[this.nodes.length - 1].id}", END)` : ''}

        # 编译工作流
        app = workflow.compile()
        return app

    async def run(self, context) -> Any:
        """执行工作流"""
        try:
            # 初始化状态
            initial_state = {
                "messages": [],
                "current_step": "",
                "input_data": context.input_data,
                "output_data": {},
                "metadata": {"workflow_id": context.workflow_id}
            }

            # 运行工作流
            result = await self.graph.ainvoke(initial_state)

            logger.info(f"Workflow completed: {context.workflow_id}")
            return result.get("output_data", {})

        except Exception as e:
            logger.error(f"Workflow execution error: {str(e)}")
            raise`,
          },
        ],
        subdirectories: [],
      },
    }
  }

  private generateLayer5(): LayeredCodeV2 {
    const toolNodes = this.nodes.filter((node) => {
      const type = node.data.type
      return type === "tool" || type.includes("tool") || type === "http" || type === "api"
    })

    return {
      layer: "Layer 4",
      title: "工具与集成层 (Tools & Integration Layer)",
      description: `标准工具、MCP集成模块、工具注册表 - 检测到 ${toolNodes.length} 个工具节点`,
      color: "#fce4ec",
      directory: {
        name: "tools",
        path: "/tools",
        files: [
          {
            name: "__init__.py",
            path: "/tools/__init__.py",
            language: "python",
            content: `from .manager import ToolManager, tool_manager
from .mcp_integration import MCPIntegration

__all__ = ["ToolManager", "tool_manager", "MCPIntegration"]`,
          },
          {
            name: "manager.py",
            path: "/tools/manager.py",
            language: "python",
            content: `from langchain.tools import Tool
from typing import List, Dict, Any

class ToolManager:
    """工具管理器"""

    def __init__(self):
        self.tools: Dict[str, Tool] = {}
        self.register_builtin_tools()

    def register_builtin_tools(self):
        """注册内置工具 - 基于 ${toolNodes.length} 个工具节点"""
${toolNodes.length > 0 ? toolNodes.map(node => {
  const toolName = this.sanitizeName(node.id)
  return `
        # ${node.data.label}
        self.tools["${toolName}"] = Tool(
            name="${toolName}",
            description="${node.data.label}",
            func=self.${toolName}_impl
        )`
}).join('\n') : '        # 暂无工具节点'}

    def get_tool(self, tool_name: str) -> Tool:
        """获取工具实例"""
        if tool_name not in self.tools:
            raise ValueError(f"Tool not found: {tool_name}")
        return self.tools[tool_name]

    def get_all_tools(self) -> List[Tool]:
        """获取所有工具"""
        return list(self.tools.values())

# 全局工具管理器
tool_manager = ToolManager()`,
          },
          {
            name: "mcp_integration.py",
            path: "/tools/mcp_integration.py",
            language: "python",
            content: `import httpx
from typing import Dict, Any

class MCPIntegration:
    """MCP (Model Context Protocol) 集成"""

    def __init__(self, server_url: str):
        self.server_url = server_url
        self.client = httpx.AsyncClient()

    async def call_mcp_tool(
        self,
        tool_name: str,
        params: Dict[str, Any]
    ) -> Any:
        """调用 MCP 工具"""
        response = await self.client.post(
            f"{self.server_url}/tools/{tool_name}",
            json=params
        )
        return response.json()

    async def close(self):
        """关闭客户端"""
        await self.client.aclose()`,
          },
        ],
        subdirectories: [],
      },
    }
  }

  private generateLayer6(): LayeredCodeV2 {
    return {
      layer: "Layer 5",
      title: "基础设施层 (Infrastructure Layer)",
      description: "配置管理、模型服务、存储服务、监控服务",
      color: "#f1f8e9",
      directory: {
        name: "infrastructure",
        path: "/infrastructure",
        files: [
          {
            name: "__init__.py",
            path: "/infrastructure/__init__.py",
            language: "python",
            content: `from .config import config_manager
from .models import model_service
from .storage import storage_service
from .monitoring import monitoring_service

__all__ = [
    "config_manager",
    "model_service",
    "storage_service",
    "monitoring_service"
]`,
          },
          {
            name: "config.py",
            path: "/infrastructure/config.py",
            language: "python",
            content: `from typing import Dict, Any, Optional
import os
from pathlib import Path
import json

class ConfigManager:
    """配置管理器"""

    def __init__(self, config_path: Optional[str] = None):
        self.config_path = config_path or os.getenv("CONFIG_PATH", "config.json")
        self.config = self.load_config()

    def load_config(self) -> Dict[str, Any]:
        """加载配置"""
        if Path(self.config_path).exists():
            with open(self.config_path, 'r') as f:
                return json.load(f)
        return self.get_default_config()

    def get_default_config(self) -> Dict[str, Any]:
        """获取默认配置"""
        return {
            "model": {
                "provider": "openai",
                "model_name": "gpt-4",
                "temperature": 0.7,
                "max_tokens": 2000
            },
            "storage": {
                "type": "local",
                "path": "./data"
            },
            "monitoring": {
                "enabled": True,
                "log_level": "INFO"
            },
            "workflow": {
                "nodes": ${this.nodes.length},
                "edges": ${this.edges.length}
            }
        }

# 全局配置管理器
config_manager = ConfigManager()`,
          },
          {
            name: "models.py",
            path: "/infrastructure/models.py",
            language: "python",
            content: `from typing import Dict, Any
from langchain_openai import ChatOpenAI

class ModelService:
    """模型服务"""

    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.model = self.initialize_model()

    def initialize_model(self):
        """初始化模型"""
        return ChatOpenAI(
            model=self.config.get("model_name", "gpt-4"),
            temperature=self.config.get("temperature", 0.7),
            max_tokens=self.config.get("max_tokens", 2000)
        )

    async def generate(self, prompt: str) -> str:
        """生成文本"""
        response = await self.model.ainvoke(prompt)
        return response.content

# 全局模型服务
from .config import config_manager
model_service = ModelService(config_manager.config.get("model", {}))`,
          },
          {
            name: "storage.py",
            path: "/infrastructure/storage.py",
            language: "python",
            content: `from typing import Dict, Any, Optional
from pathlib import Path
import json

class StorageService:
    """存储服务"""

    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.storage_path = Path(config.get("path", "./data"))
        self.storage_path.mkdir(parents=True, exist_ok=True)

    async def save(self, key: str, data: Any) -> bool:
        """保存数据"""
        file_path = self.storage_path / f"{key}.json"
        with open(file_path, 'w') as f:
            json.dump(data, f, indent=2)
        return True

    async def load(self, key: str) -> Optional[Any]:
        """加载数据"""
        file_path = self.storage_path / f"{key}.json"
        if file_path.exists():
            with open(file_path, 'r') as f:
                return json.load(f)
        return None

# 全局存储服务
from .config import config_manager
storage_service = StorageService(config_manager.config.get("storage", {}))`,
          },
          {
            name: "monitoring.py",
            path: "/infrastructure/monitoring.py",
            language: "python",
            content: `from typing import Dict, Any
import logging

class MonitoringService:
    """监控服务"""

    def __init__(self, config: Dict[str, Any]):
        self.enabled = config.get("enabled", True)
        self.metrics: Dict[str, Any] = {}
        self.setup_logging(config.get("log_level", "INFO"))

    def setup_logging(self, level: str):
        """设置日志"""
        logging.basicConfig(
            level=getattr(logging, level),
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )

    def track_metric(self, name: str, value: Any):
        """记录指标"""
        if self.enabled:
            self.metrics[name] = value

    def get_metrics(self) -> Dict[str, Any]:
        """获取指标"""
        return self.metrics

# 全局监控服务
from .config import config_manager
monitoring_service = MonitoringService(config_manager.config.get("monitoring", {}))`,
          },
          {
            name: "config.json",
            path: "/infrastructure/config.json",
            language: "json",
            content: `{
  "model": {
    "provider": "openai",
    "model_name": "gpt-4",
    "temperature": 0.7,
    "max_tokens": 2000
  },
  "storage": {
    "type": "local",
    "path": "./data"
  },
  "monitoring": {
    "enabled": true,
    "log_level": "INFO"
  },
  "workflow": {
    "id": "${this.workflowId}",
    "nodes": ${this.nodes.length},
    "edges": ${this.edges.length}
  }
}`,
          },
        ],
        subdirectories: [],
      },
    }
  }

  private generateNodeFunctions(): string {
    const implementations: string[] = []

    this.nodes.forEach((node) => {
      const config = this.nodeConfigs.get(node.data.type)
      if (!config) return

      const functionName = this.sanitizeName(node.id)
      const paramValues = node.data.parameterValues || {}
      const inputParams = config.inputs.map(i => `${i.name}: ${JSON.stringify(paramValues[i.name] || 'None')}`).join(', ')

      implementations.push(`async def ${functionName}(state: WorkflowState) -> WorkflowState:
    """
    节点: ${node.data.label}
    类型: ${config.label}
    描述: ${config.description}
    输入参数: ${config.inputs.map(i => i.name).join(', ') || '无'}
    输出参数: ${config.outputs.map(o => o.name).join(', ') || '无'}
    """
    logger.info(f"执行节点: ${node.data.label} (${node.id})")

    try:
        # 节点具体实现
        # 配置参数: ${JSON.stringify(paramValues)}

        result = {
            "status": "completed",
            "node_id": "${node.id}",
            "node_label": "${node.data.label}",
            "node_type": "${config.label}",
            "params": ${JSON.stringify(paramValues)}
        }

        # 更新状态
        state["messages"].append(f"✓ ${node.data.label}")
        state["current_step"] = "${node.id}"
        state["${this.sanitizeName(node.id)}_result"] = result
        state["output_data"]["${functionName}"] = result

        return state

    except Exception as e:
        logger.error(f"节点 ${node.data.label} 执行失败: {str(e)}")
        state["messages"].append(f"✗ ${node.data.label}: {str(e)}")
        raise`)
    })

    return implementations.join('\n\n')
  }

  private generateFullCode(layers: LayeredCodeV2[]): string {
    const sections: string[] = []

    sections.push(`"""
${this.workflowId} - LangGraph 工作流
自动生成的分层架构代码

工作流信息:
- 节点数量: ${this.nodes.length}
- 连接数量: ${this.edges.length}
- 生成时间: ${new Date().toISOString()}
- 节点列表: ${this.nodes.map(n => n.data.label).join(', ')}

目录结构:
${layers.map(layer => `- ${layer.directory.path}/ (${layer.title})`).join('\n')}
"""

`)

    // 合并所有层的代码
    layers.forEach((layer) => {
      sections.push(`# ${"=".repeat(80)}`)
      sections.push(`# ${layer.title}`)
      sections.push(`# ${layer.description}`)
      sections.push(`# ${"=".repeat(80)}`)
      sections.push(``)
      this.appendDirectoryCode(layer.directory, sections)
      sections.push(``)
    })

    return sections.join("\n")
  }

  private appendDirectoryCode(dir: DirectoryNode, sections: string[]) {
    dir.files.forEach((file) => {
      sections.push(`# 文件: ${file.path}`)
      sections.push(file.content)
      sections.push(``)
    })

    dir.subdirectories.forEach((subdir) => {
      this.appendDirectoryCode(subdir, sections)
    })
  }

  private sanitizeName(name: string): string {
    return name.replace(/[^a-zA-Z0-9_]/g, "_").replace(/^[0-9]/, "_$&")
  }
}

/**
 * 便捷函数：生成 LangGraph 代码 V2
 */
export function generateLangGraphCodeV2(
  nodes: Node[],
  edges: Edge[],
  nodeConfigs: NodeConfig[],
): GeneratedLangGraphCodeV2 {
  const generator = new LangGraphCodeGeneratorV2(nodes, edges, nodeConfigs)
  return generator.generate()
}
